home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-07 | 26.0 KB | 670 lines | [TEXT/CCL2] |
- ;;;
- ;;; object-fred-dialog-item.lisp
- ;;;
-
- #|
- ================================================================
- Purpose ========================================================
- ================================================================
- Defines the object-fred-dialog-item subclass of fred-dialog-item that
- incorporates embedded objects.
-
- We care about these conditions:
-
- Object text is selected. (Must extend selection.)
- Happens via mouse, keystrokes, or programmatically. Ignore latter for now
- (fix?).
-
- Object text is deleted. (Must delete object entry.)
- Happens via keystrokes or programmatically. Ignore latter for now (fix?).
-
-
- ==== To use this file ====
- (Note: Generic functions specify the interface.)
-
- This file defines the object-fred-dialog-item subclass of
- fred-dialog-item, which knows how to display strings and non-string
- objects. Strings are displayed in the font specified by
- object-fred-dialog-item's font-spec-string slot, and non-string objects
- are displayed as specified by the font-spec-non-string slot.
-
- To edit a list of strings and non-string objects create a
- object-fred-dialog-item instance and call edit-l-data on it and the data
- to be initially edited. In all cases the "data" involved is a list of
- strings and non-string objects. Non-string objects are converted to
- strings via string-from-object, which you can redefine. You can call
- add-link to add new objects. Three functions return data in
- object-fred-dialog-items: l-str-obj-ofdi (returns all items),
- l-str-obj-ofdi-selected (returns selected items), and
- l-str-obj-ofdi-in-range (returns items in a range).
-
-
- ================================================================
- Status =========================================================
- ================================================================
- Usable.
-
- Copyright © 1990-92 Matthew Cornell. All Rights Reserved. Send
- bugs, comments, questions, and fixes to cornell@cs.umass.edu.
-
- Undo not implemented.
-
- Changing font-spec-string and font-spec-non-string after creating
- doesn't change the current display.
-
- Not all font-setting functions stopped (e.g. buffer-set-font-spec) so it's
- possible our pretty font scheme might be messed up.
-
- Bug: auto-fill.lisp calls buffer-char-replace and buffer-insert which I
- don't advise.
-
-
- ================================================================
- Change history =================================================
- ================================================================
- 29-Jul-92 mc Created.
- 01-Aug-92 mc Moved to CCL package. Added some documentation.
- 02-Aug-92 mc Added generic functions, wrote l-str-obj-ofdi-in-range and
- friends.
- 03-Aug-92 mc Fixed bug in l-str-obj-ofdi-in-range that returned wrong
- values for indices within an object.
- 10-Aug-92 mc Defined string-from-object .
- 15-Aug-92 mc Moved mouse-copy hook to "object-FDI-mouse-copy-glue.lisp" .
- 06-Sep-92 mc Fixed bug in advised buffer-delete (didn't handle marks for
- third arg).
-
- |#
-
-
- (in-package "CCL")
-
- (export '(OBJECT-FRED-DIALOG-ITEM
- FONT-SPEC-STRING-OFDI
- FONT-SPEC-NON-STRING-OFDI
- ADD-LINK
- EDIT-L-DATA
- L-STR-OBJ-OFDI
- L-STR-OBJ-OFDI-SELECTED
- L-STR-OBJ-OFDI-IN-RANGE
- STRING-FROM-OBJECT
- *L-OBJECT-GIVEN*))
-
-
- ;;;================================================================
- ;;; Define the object-fred-dialog-item class and methods.
- ;;;================================================================
-
- (defclass object-fred-dialog-item (fred-dialog-item) ;super s/b fred-mixin?
- ((l-l-obj-marks
- :accessor l-l-obj-marks-ofdi
- :type list
- :initform ()
- :documentation "A sorted list of lists used by edit-l-data and
- l-str-obj-ofdi. Each sublist is a list of a non-string object,
- its start mark, and its string representation. Add-link adds items to
- the list and maintains its sorted order, which is in ascending order of
- position.")
- (font-spec-string
- :accessor font-spec-string-ofdi
- :type list
- :initarg :font-spec-string
- :initform '("Geneva" 9 :plain)
- :documentation "The font spec to display strings in.")
- (font-spec-non-string
- :accessor font-spec-non-string-ofdi
- :type list
- :initarg :font-spec-string
- :initform '("Geneva" 9 :plain :bold)
- :documentation "The font spec to display non-string objects in.")
- (f-paste-with-styles-saved
- :accessor f-paste-with-styles-saved-ofdi
- :initform *paste-with-styles*
- :type t
- :documentation "The saved value of *paste-with-styles* .")
- )
- (:default-initargs
- :allow-returns t
- :allow-tabs t
- :copy-styles-p nil))
-
-
- ;;;================================================================
- ;;; Define support for the advised functions.
- ;;;================================================================
-
- (defparameter *object-fred-dialog-item-editing* nil
- "Bound to the object-fred-dialog-item within which a deletion or section
- is being done. Used to communicate between view-key-event-handler and
- view-click-event-handler, and the advised buffer-delete
- frec-set-sel and frec-set-sel-simple .")
-
-
- ;;; We advise buffer-delete to know, regardless of how the deletion is
- ;;; initiated, what the range about to be deleted is.
-
- (advise buffer-delete
- ;; Arglist: buffer-mark start &optional end
- (cond (*object-fred-dialog-item-editing*
- ;; Start and end might delete part of an object.
- (unless (maybe-delete-objects
- *object-fred-dialog-item-editing*
- (second arglist)
- (if (third arglist)
- (if (buffer-mark-p (third arglist))
- (buffer-position (third arglist))
- (third arglist))
- (buffer-position (first arglist))))
- (:do-it)))
- (t (:do-it)))
- :when :around
- :name maybe-delete-objects)
-
-
-
- #|
- (advise buffer-insert
- ;; Arglist: buffer-mark string &optional position
- (cond (*object-fred-dialog-item-editing*
- ;; Position might be within an object.
- (let ((int-position (or (third arglist)
- (buffer-position (first arglist)))))
- (if (l-str-obj-ofdi-in-range
- *object-fred-dialog-item-editing*
- int-position int-position)
- nil ;(ed-beep)
- (:do-it))))
- (t (:do-it)))
- :when :around
- :name maybe-delete-objects)
- |#
-
-
- #|
- ;;; We need advise frec-set-sel and frec-set-sel-simple to catch
- ;;; programmatic changing of selections. But then we must get the
- ;;; fred-mixin item from the args to call maybe-extend-selection! Don't do
- ;;; for now.
-
- (advise frec-set-sel
- (when *object-fred-dialog-item-editing*
- (maybe-extend-selection *object-fred-dialog-item-editing*))
- :when :after
- :name maybe-extend-selection)
-
- (advise frec-set-sel-simple
- (when *object-fred-dialog-item-editing*
- (maybe-extend-selection *object-fred-dialog-item-editing*))
- :when :after
- :name maybe-extend-selection)|#
-
-
- ;;;================================================================
- ;;; Define window event functions.
- ;;;================================================================
-
- (defmethod view-key-event-handler ((object-fred-dialog-item object-fred-dialog-item)
- character)
- (declare (ignore character)
- (optimize speed))
- ;;
- ;; Following form catches deletions via the advised buffer-delete .
- ;;
- (let ((*object-fred-dialog-item-editing* object-fred-dialog-item))
- (call-next-method))
- ;;
- ;; Following form catches selection range changes via keystrokes.
- ;;
- (maybe-extend-selection object-fred-dialog-item))
-
-
- (defmethod view-click-event-handler ((object-fred-dialog-item object-fred-dialog-item)
- where)
- (declare (ignore where)
- (optimize speed))
- ;;
- (let ((*object-fred-dialog-item-editing* nil)) ;otherwise causes infinite loop
- (call-next-method))
- ;;
- ;; Following form catches selection range changes via mouse.
- ;;
- (maybe-extend-selection object-fred-dialog-item))
-
-
- (defmethod view-activate-event-handler :after ((object-fred-dialog-item object-fred-dialog-item))
- "Saves *paste-with-styles* and sets it to nil so that all inserted text
- is in font-spec-string-ofdi ."
- (declare (optimize speed))
- ;;
- (setf (f-paste-with-styles-saved-ofdi object-fred-dialog-item) *paste-with-styles*
- *paste-with-styles* nil))
-
-
- (defmethod view-deactivate-event-handler :after ((object-fred-dialog-item object-fred-dialog-item))
- "Restores *paste-with-styles* ."
- (declare (optimize speed))
- ;;
- (setf *paste-with-styles* (f-paste-with-styles-saved-ofdi object-fred-dialog-item)))
-
-
- (defmethod undo ((object-fred-dialog-item object-fred-dialog-item))
- "Calls ed-beep for now. Fix (will just call usual?)."
- (declare (optimize speed))
- ;;
- (ed-beep))
-
-
- (defmethod set-view-font ((object-fred-dialog-item object-fred-dialog-item)
- font-spec)
- "Does nothing so that our font scheme isn't messed up."
- (declare (optimize speed))
- ;;
- font-spec)
-
-
- ;;;================================================================
- ;;; Define support for window event functions.
- ;;;================================================================
-
- ;;; Fix: Call setup-undo (see p. 363, ch. 12: Programming Fred) to handle
- ;;; re-inserting and re-deleting links. The former should call add-link.
-
- (defmethod maybe-delete-objects ((object-fred-dialog-item object-fred-dialog-item)
- (int-index-delete-start integer)
- (int-index-delete-end integer))
- "Deletes the entry in object-fred-dialog-item's l-l-obj-marks-ofdi corresponding to
- the about-to-be-deleted range in object-fred-dialog-item specified by
- int-index-delete-start and int-index-delete-end . Should be called
- before the specified range is about to be deleted. Returns f-delete-done
- which is non-nil when maybe-delete-objects has taken care of deleting the
- passed range."
- (declare (optimize speed))
- ;;
- ;; If there are selected objects in the range then delete them as part of
- ;; their text being deleted.
- ;;
- (let* ((buffer (fred-buffer object-fred-dialog-item))
- (l-l-obj-marks-in-range
- (l-l-obj-marks-in-range object-fred-dialog-item int-index-delete-start int-index-delete-end))
- (l-obj-mark-in-range-first (first l-l-obj-marks-in-range))
- (l-obj-mark-in-range-last (first (last l-l-obj-marks-in-range)))
- ;; Following two computations depend on l-l-obj-marks-ofdi being
- ;; sorted in ascending order of position:
- (int-index-first-obj-start
- (and l-l-obj-marks-in-range
- (multiple-value-bind (int-index-obj-start int-index-obj-end)
- (int-index-object-bounds l-obj-mark-in-range-first)
- (declare (ignore int-index-obj-end))
- ;;
- int-index-obj-start)))
- (int-index-last-obj-end
- (and l-l-obj-marks-in-range
- (multiple-value-bind (int-index-obj-start int-index-obj-end)
- (int-index-object-bounds l-obj-mark-in-range-last)
- (declare (ignore int-index-obj-start))
- ;;
- int-index-obj-end)))
- (int-index-delete-start-actual
- (and l-l-obj-marks-in-range (min int-index-delete-start
- int-index-first-obj-start)))
- (int-index-delete-end-actual
- (and l-l-obj-marks-in-range (max int-index-delete-end
- int-index-last-obj-end)))
- (f-delete-done l-l-obj-marks-in-range))
- ;;
- ;; Note: It may be that deleting the passed range will not delete all
- ;; of l-l-obj-marks-in-range's object text.
- ;;
- (when l-l-obj-marks-in-range
- (let ((*object-fred-dialog-item-editing* nil)) ;otherwise causes infinite loop
- (buffer-delete buffer
- int-index-delete-start-actual int-index-delete-end-actual))
- (setf (l-l-obj-marks-ofdi object-fred-dialog-item)
- (delete-if #'(lambda (l-obj-marks-ew)
- (member l-obj-marks-ew l-l-obj-marks-in-range))
- (l-l-obj-marks-ofdi object-fred-dialog-item))))
- ;;
- f-delete-done))
-
-
- (defmethod maybe-extend-selection ((object-fred-dialog-item object-fred-dialog-item))
- "Extends the selection if part of it touches an object's text."
- (declare (optimize speed))
- ;;
- (let (int-index-selection-start
- int-index-selection-end)
- (dolist (l-obj-marks (l-l-obj-marks-ofdi object-fred-dialog-item))
- ;; We call selection-range each time because previous calls to
- ;; maybe-extend-object may have changed it.
- (multiple-value-setq (int-index-selection-start int-index-selection-end)
- (selection-range object-fred-dialog-item))
- (maybe-extend-object object-fred-dialog-item l-obj-marks
- int-index-selection-start
- int-index-selection-end))))
-
-
- (defmethod maybe-extend-object ((object-fred-dialog-item object-fred-dialog-item)
- (l-obj-marks list)
- (int-index-selection-start integer)
- (int-index-selection-end integer))
- "Extends if necessary the selection corresponding to the object in
- l-obj-marks."
- (declare (optimize speed))
- ;;
- (multiple-value-bind (int-index-obj-start int-index-obj-end)
- (int-index-object-bounds l-obj-marks)
- (let* ((f-extend-start
- (and (< int-index-obj-start int-index-selection-start)
- (< int-index-selection-start int-index-obj-end)))
- (f-extend-end
- (and (< int-index-obj-start int-index-selection-end)
- (< int-index-selection-end int-index-obj-end))))
- (set-selection-range
- object-fred-dialog-item
- (if f-extend-start int-index-obj-start int-index-selection-start)
- (if f-extend-end int-index-obj-end int-index-selection-end))
- (fred-update object-fred-dialog-item))))
-
-
- ;;;================================================================
- ;;; Define functions that return information about objects, whether they're
- ;;; selected, and their bounds.
- ;;;================================================================
-
- (defmethod int-index-object-bounds ((l-obj-marks list))
- "Returns two values, int-index-obj-start (inclusive) and
- int-index-obj-end (exclusive), corresonding to the object in
- l-obj-marks."
- (declare (optimize speed))
- ;;
- (let ((int-index-obj-start (buffer-position (second l-obj-marks))))
- (values int-index-obj-start
- (+ int-index-obj-start (length (third l-obj-marks))))))
-
-
- (defmethod l-l-obj-marks-in-range ((object-fred-dialog-item object-fred-dialog-item)
- (int-index-range-start integer)
- (int-index-range-end integer))
- "Returns a list of the objects in object-fred-dialog-item whose boundaries are
- either includeded by or contain the range specified by
- int-index-range-start and int-index-range-end. The returned list in the
- same format as object-fred-dialog-item's l-l-obj-marks slot."
- (declare (optimize speed))
- ;;
- (remove-if-not
- #'(lambda (l-obj-marks-ew)
- (multiple-value-bind (int-index-obj-start int-index-obj-end)
- (int-index-object-bounds l-obj-marks-ew)
- (or (< int-index-obj-start int-index-range-start int-index-obj-end)
- (< int-index-obj-start int-index-range-end int-index-obj-end)
- (and (<= int-index-range-start
- int-index-obj-start)
- (<= int-index-obj-end
- int-index-range-end)))))
- (l-l-obj-marks-ofdi object-fred-dialog-item)))
-
-
- (defmethod l-l-obj-marks-selected ((object-fred-dialog-item object-fred-dialog-item))
- "Returns a list of the objects currently selected in object-fred-dialog-item, in the
- same format as object-fred-dialog-item's l-l-obj-marks slot."
- (declare (optimize speed))
- ;;
- (multiple-value-bind (int-index-selection-start int-index-selection-end)
- (selection-range object-fred-dialog-item)
- (l-l-obj-marks-in-range object-fred-dialog-item
- int-index-selection-start int-index-selection-end)))
-
-
- ;;;================================================================
- ;;; Define the top-level methods for using object-fred-dialog-items.
- ;;;================================================================
-
- (defgeneric add-link (object-fred-dialog-item object int-index)
- (:documentation "Adds a link to object in object-fred-dialog-item at
- int-index."))
-
-
- (defmethod add-link ((object-fred-dialog-item object-fred-dialog-item)
- (object t)
- (int-index integer))
- (declare (optimize speed))
- ;;
- (when (stringp object)
- (error "~S is a string and should be any non-string object." object))
- ;;
- (let* ((buffer (fred-buffer object-fred-dialog-item))
- int-index-start
- str-data)
- ;;
- ;; If object-fred-dialog-item has a selection delete it.
- ;;
- (multiple-value-bind (int-index-selection-start int-index-selection-end)
- (selection-range object-fred-dialog-item)
- (unless (= int-index-selection-start int-index-selection-end)
- (maybe-delete-objects object-fred-dialog-item
- int-index-selection-start int-index-selection-end)
- (buffer-delete buffer int-index-selection-start int-index-selection-end)))
- ;;
- ;; Insert a new link.
- ;;
- (setf int-index-start (buffer-position buffer))
- (buffer-set-font-spec buffer (font-spec-non-string-ofdi object-fred-dialog-item))
- (setf str-data (string-from-object object object-fred-dialog-item))
- (buffer-insert buffer str-data)
- ;; Make the mark *after* the insert so that it doesn't move on us.
- (push (list object (make-mark buffer int-index-start) str-data)
- (l-l-obj-marks-ofdi object-fred-dialog-item))
- (sort-l-l-obj-marks-ofdi object-fred-dialog-item)
- (buffer-set-font-spec buffer (font-spec-string-ofdi object-fred-dialog-item))
- (fred-update object-fred-dialog-item)))
-
-
- (defgeneric edit-l-data (l-data object-fred-dialog-item)
- (:documentation "Starts editing in object-fred-dialog-item the
- information in l-data. L-data is a list of strings and non-string
- objects. The user can edit the string portion of l-data but can only
- select and delete non-string objects. Calling "))
-
-
- (defmethod edit-l-data ((l-data list) (object-fred-dialog-item object-fred-dialog-item))
- (declare (optimize speed))
- ;;
- ;; Insert each item on l-data into buffer. If it's a string then insert
- ;; it using (font-spec-string-ofdi object-fred-dialog-item). Otherwise insert it using
- ;; (font-spec-non-string-ofdi object-fred-dialog-item), add a new entry for the object in
- ;; (l-l-obj-marks-ofdi object-fred-dialog-item) with new start and end marks.
- ;;
- (let ((buffer (fred-buffer object-fred-dialog-item)))
- (setf (l-l-obj-marks-ofdi object-fred-dialog-item) ())
- (buffer-delete buffer 0 (buffer-size buffer)) ;delete all buffer's text
- (dolist (data l-data)
- (typecase data
- (string
- (buffer-set-font-spec buffer (font-spec-string-ofdi object-fred-dialog-item))
- (buffer-insert buffer data))
- (t
- (add-link object-fred-dialog-item data (buffer-position buffer)))))
- ;;
- ;; Correct buffer's insertion font so typing will be correct, then
- ;; show the updated buffer.
- ;;
- (buffer-set-font-spec buffer (font-spec-string-ofdi object-fred-dialog-item))
- (fred-update object-fred-dialog-item)))
-
-
- (defgeneric l-str-obj-ofdi (object-fred-dialog-item)
- (:documentation "Returns l-str-obj, which contains in order all the
- strings and objects in object-fred-dialog-item."))
-
-
- (defmethod l-str-obj-ofdi ((object-fred-dialog-item object-fred-dialog-item))
- (declare (optimize speed))
- ;;
- (let ((buffer (fred-buffer object-fred-dialog-item)))
- (l-str-obj-ofdi-in-range object-fred-dialog-item
- 0 (buffer-size buffer))))
-
-
- (defgeneric l-str-obj-ofdi-selected (object-fred-dialog-item)
- (:documentation "Returns l-str-obj, which contains in order all the
- strings and objects in object-fred-dialog-item's current selection
- range."))
-
-
- (defmethod l-str-obj-ofdi-selected ((object-fred-dialog-item object-fred-dialog-item))
- (declare (optimize speed))
- ;;
- (multiple-value-bind (int-index-selection-start int-index-selection-end)
- (selection-range object-fred-dialog-item)
- (l-str-obj-ofdi-in-range object-fred-dialog-item
- int-index-selection-start int-index-selection-end)))
-
-
- (defgeneric l-str-obj-ofdi-in-range (object-fred-dialog-item
- int-index-start
- int-index-end)
- (:documentation "Returns l-str-obj, which contains in order all the
- strings and objects in object-fred-dialog-item's between int-index-start
- (inclusive) and int-index-end (exclusive)."))
-
-
- (defmethod l-str-obj-ofdi-in-range ((object-fred-dialog-item object-fred-dialog-item)
- (int-index-start integer)
- (int-index-end integer))
- (declare (optimize speed))
- ;;
- (let ((l-str-obj ())
- (int-index-prev-str int-index-start)
- (buffer (fred-buffer object-fred-dialog-item))
- int-index-obj-start int-index-obj-end)
- ;;
- ;; For each object, save the string preceding it onto l-str-obj then
- ;; save the object itself. The string's start is in
- ;; int-index-prev-str. Depends on l-l-obj-marks-ofdi being sorted in
- ;; ascending order of position.
- ;;
- (dolist (l-obj-marks (l-l-obj-marks-in-range object-fred-dialog-item
- int-index-start
- int-index-end))
- (multiple-value-setq (int-index-obj-start int-index-obj-end)
- (int-index-object-bounds l-obj-marks))
- (when (and (/= int-index-prev-str int-index-obj-start)
- (not (<= int-index-obj-start int-index-prev-str int-index-obj-end)))
- ;; We have a preceding string so save it.
- (push (buffer-substring buffer int-index-prev-str int-index-obj-start)
- l-str-obj))
- (push (first l-obj-marks) l-str-obj)
- (setf int-index-prev-str int-index-obj-end))
- ;;
- ;; Add the final string if there is one and return the result.
- ;;
- (when (or (null int-index-obj-end)
- (< int-index-obj-end int-index-end))
- (push (buffer-substring buffer int-index-prev-str int-index-end)
- l-str-obj))
- (reverse l-str-obj)))
-
-
- (defgeneric string-from-object (object object-fred-dialog-item)
- (:documentation "Returns a textual representation of object as a string.
- T's version (the default for all objects), returns the object's ~S
- format string."))
-
-
- (defmethod string-from-object ((object t)
- (object-fred-dialog-item object-fred-dialog-item))
- (declare (optimize speed)
- (ignore object-fred-dialog-item))
- ;;
- (format nil "~S" object))
-
-
- ;;;================================================================
- ;;; Define remaining support functions.
- ;;;================================================================
-
- (defmethod sort-l-l-obj-marks-ofdi ((object-fred-dialog-item object-fred-dialog-item))
- "Sorts l-l-obj-marks-ofdi in ascending order of position."
- (declare (optimize speed))
- ;;
- (setf (l-l-obj-marks-ofdi object-fred-dialog-item)
- (sort (l-l-obj-marks-ofdi object-fred-dialog-item)
- #'<
- :key #'(lambda (l-obj-mark)
- (buffer-position (second l-obj-mark))))))
-
-
- (provide "OBJECT-FRED-DIALOG-ITEM")
-
-
- #|
-
- ;;; See "object-FDI-mouse-copy-glue.lisp" for another example.
-
- ;;; Define testing code.
-
- (defclass describing-ofdi (object-fred-dialog-item)
- ()
- (:documentation "A subclass of object-fred-dialog-item that describes the
- current selection."))
-
-
- (defmethod view-click-event-handler :after ((describing-ofdi describing-ofdi)
- where)
- (declare (ignore where)
- (optimize speed))
- ;;
- (when (double-click-p)
- (let ((l-str-obj-ofdi-selected (l-str-obj-ofdi-selected describing-ofdi)))
- (when l-str-obj-ofdi-selected
- (dolist (l-str-obj l-str-obj-ofdi-selected)
- (format t "~&~A:~20T~S." (type-of l-str-obj) l-str-obj))))))
-
-
- (defclass temp ()()
- (:documentation "A class of objects that prints with a #\), so I can test
- killing into an object."))
-
- (defmethod print-object ((object temp) stream)
- (princ "<Bad ) >" stream))
-
-
- (defparameter *l-data-test* (list "Dear "
- '|Mary|
- (format nil ":~%On ")
- 23
- " we dis(cussed "
- (make-instance 'temp)
- ;(make-instance 'menu-item)
- (format nil "~%which we both liked."))
- "The test data used by test.")
-
-
- (defparameter *window-test* nil
- "The edit window used by test.")
-
- (defparameter *ofdi-test* nil
- "The object-fred-dialog-item used by test.")
-
-
- (defun test-ofdi ()
- (when (or (null *window-test*)
- (null (wptr *window-test*)))
- (setf *ofdi-test* (make-instance 'describing-ofdi
- :view-position #@(3 3)
- :view-size #@(300 200))
- *window-test* (make-instance 'window :window-title "Test OFDI"
- :window-type :document
- :view-size #@(302 202)
- :view-subviews (list *ofdi-test*))))
- (edit-l-data *l-data-test* *ofdi-test*))
-
-
- (defun f-editing-loop-ok ()
- "Returns non-nil if the result of running test then calling
- l-str-obj-ofdi changes *l-data-test* ."
- ;;
- (let ((l-data-test-initial *l-data-test*))
- (test)
- (equalp l-data-test-initial
- (l-str-obj-ofdi *ofdi-test*))))
- |#